package main

import (
	"bufio"
	"fmt"
	"os/exec"
	"strings"
	"time"
)

func Handle(dirName, appName, runCmd, buildCmd, buildDir, lang string) {
	if !strings.HasSuffix(buildDir, "/") {
		buildDir = buildDir + "/"
	}
	cmd := `go build -o ` + buildDir + appName
	runProcess := "\\/" + appName
	if lang == "rust" {
		cmd = "cargo run"
		runProcess = "cargo run"
	}
	pid, _ := CheckProRunning(cmd)
	fmt.Println("--- process is running now, pid: ", pid)
	if pid == "" {
		_, err := RunCommand(cmd)
		if err == nil {
			pid, _ := CheckProRunning(runProcess)
			if pid != "" {
				fmt.Println("--- kill " + appName + " process: " + pid)
				RunCommand("kill -9 " + pid)
			}
			pid2, _ := CheckProRunning(appName + `_eye.sh`)
			if pid2 != "" {
				RunCommand("kill -9 " + pid2)
				fmt.Println("kill "+appName+"_eye.sh: ", pid2)
			}
			result, _ := GetOutputContinually(appName)
			<-result
			//}()
		}
		if err != nil {
			fmt.Println(err)
			return
		}
	} else {
		fmt.Println("--- " + time.Now().Format("2006-01-02 15:04:05") + " last build process is running, please waiting")
	}

}

// 根据进程名判断进程是否运行
func CheckProRunning(serverName string) (string, error) {
	/*b := `ps ux | awk '/(` + serverName + `$)|(` + serverName + ` +)/'`

	t, _ := RunCommand(b)
	fmt.Println(t, b, "%%%%%%%%%")*/
	a := `ps ux | awk '/(` + serverName + `$)|(` + serverName + ` +)/ && !/awk/ {print $2}'`
	pid, err := RunCommand(a)
	//fmt.Println(a, pid, "&&&&&&&&")
	if err != nil {
		return "", err
	}
	return pid, nil
}

// 根据进程名称获取进程ID
func GetPid(serverName string) (string, error) {
	a := `ps ux | awk '/` + serverName + `/ && !/awk/ {print $2}'`
	pid, err := RunCommand(a)
	return pid, err
}

// 在命令执行结束后获得系统输出结果
func RunCommand(script string) (string, error) {
	cmd := exec.Command("/bin/sh", "-c", script)
	//cmd := exec.Command(script)
	//fmt.Println(script, "##########")
	result, err := cmd.CombinedOutput()
	if err != nil {
		fmt.Println("\"", script, "\" error: ")
		fmt.Println("result: ", string(result))
		fmt.Println("error: ", err)
		return strings.TrimSpace(string(result)), err
	}
	return strings.TrimSpace(string(result)), nil
}

// 在命令执行过程中获得系统输出信息
func GetOutputContinually(appName string) (<-chan struct{}, error) {
	cmd := exec.Command("sh", appName+`_eye.sh`)
	fmt.Println("--- "+time.Now().Format("2006-01-02 15:04:05"), appName+" start")
	closed := make(chan struct{})
	defer close(closed)

	stdoutPipe, err := cmd.StdoutPipe()
	if err != nil {
		fmt.Println(err)
		return closed, err
	}
	defer stdoutPipe.Close()

	stderrPipe, err := cmd.StderrPipe()
	if err != nil {
		fmt.Println(err)
		return closed, err
	}
	defer stderrPipe.Close()

	go func() {
		scanner := bufio.NewScanner(stdoutPipe)
		scanner2 := bufio.NewScanner(stderrPipe)
		for scanner.Scan() || scanner2.Scan() {
			// 命令在执行的过程中, 实时地获取其输出
			if len(scanner.Bytes()) > 0 {
				fmt.Printf("%s\n", string(scanner.Bytes()))
			}
			if len(scanner2.Bytes()) > 0 {
				fmt.Printf("%s\n", string(scanner2.Bytes()))
			}
		}
	}()
	if err := cmd.Run(); err != nil {
		pid, _ := CheckProRunning(appName + `_eye.sh`)
		if pid == "" {
			fmt.Println(err, cmd)
		} else {
			RunCommand("kill -9 " + pid)
			fmt.Println("--- "+appName+" is running ... ", pid)
		}
	}
	return closed, nil
}
